package liang.jiaxin.com.utils;

import com.alibaba.dubbo.config.spring.ReferenceBean;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * Spring Bean 管理工具
 * 
 * @author Tommy
 * 
 *         2008-9-19 create
 */
@Component
public class SpringUtils implements ApplicationContextAware {

	/**
	 * 当前IOC
	 */
	private static ApplicationContext applicationContext;
	
	/**
	 * 设置当前上下文环境，此方法由spring自动装配
	 */
	@Override
	public void setApplicationContext(ApplicationContext arg0)
			throws BeansException {
		applicationContext = arg0;
	}

	/**
	 * 从当前IOC获取bean
	 * 
	 * @param id
	 *            bean的id
	 * @return
	 */
	public static Object getBean(String id) {
		Object object = null;
		object = applicationContext.getBean(id, Object.class);
		return object;
	}
	
	/**
	 * 从当前IOC获取bean
	 * 
	 * @param id
	 *            bean的id
	 * @return
	 */
	public static <T> T getBean(String id, Class<T> clazz) {
		T object = null;
		object = applicationContext.getBean(id, clazz);
		return object;
	}

	public static ApplicationContext getApplicationContext() {
		return applicationContext;
	}

	private static final ConcurrentMap<String, ReferenceBean<?>> referenceConfigs = new ConcurrentHashMap<String, ReferenceBean<?>>();

	/** 获取Dubbo服务 */
	public static Object refer(ApplicationContext applicationContext, String interfaceName) {
		String key = "/" + interfaceName + ":";
		ReferenceBean<?> referenceConfig = referenceConfigs.get(key);
		if (referenceConfig == null) {
			referenceConfig = new ReferenceBean<Object>();
			referenceConfig.setInterface(interfaceName);
			if (applicationContext != null) {
				referenceConfig.setApplicationContext(applicationContext);
				try {
					referenceConfig.afterPropertiesSet();
				} catch (RuntimeException e) {
					throw (RuntimeException)e;
				} catch (Exception e) {
					throw new IllegalStateException(e.getMessage(), e);
				}
			}
			referenceConfigs.putIfAbsent(key, referenceConfig);
			referenceConfig = referenceConfigs.get(key);
		}
		return referenceConfig.get();
	}
}
